package mobile.TheOldRepublic.video;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import mobile.TheOldRepublic.util.Downloader;

import org.apache.commons.io.IOUtils;

import android.app.ProgressDialog;
import android.content.Context;
import android.util.Log;
import android.widget.Toast;

/**
 * @deprecated No longer needed, may use later for other functions.
 */
public class VideoDownloader extends Downloader {
	
	private static final String UNZIP_VIDEO_TEXT = "Extracting Video";
	private static final String DOWNLOAD_WAIT_TEXT = "Waiting for a previous download in progress to complete.";
	
	private boolean showProgress = false;
	
	static{
		FILE_ROOT = "video.mp4";
	}
	
	private VideoDownloader(){
		
	}

	public static Downloader getInstance()
	{
		if(activeThread == null){
			activeThread = new VideoDownloader();
		}
		
		return activeThread;
	}

	/**
	 * Show progress of the download.  This can be updated in mid-download.
	 */
	public void setShowProgress(boolean value){
		this.showProgress = true;
	}
	
	@Override
	public void run(){
		if(currentDownload == null)
			this.downloadFiles();
	}
	
	private synchronized void downloadFiles()
	{
		Log.d(this.getClass().getSimpleName(), "Start downloadFiles");
		if(currentDownload != null)
			try{ wait(); }catch(InterruptedException ie){}
		Log.d(this.getClass().getSimpleName(), "wait complete");
		BgDownloadFile file;
		while((file = downloadQueue.poll()) != null){
			try{
				Log.d(this.getClass().getSimpleName(), "downloading loop "+file.inputUrl);
				currentDownload = file;
				downloadFile(file, null, true);
			}catch(IOException ioe){}
			currentDownload = null;
			Log.d(this.getClass().getSimpleName(), "yielding control");
			yield();
		}
		Log.d(this.getClass().getSimpleName(), "End downloadFiles");
	}
	
	/**
	 * Download a file as soon as possible.  This will interrupt any pending downloads but will not stop downloads that 
	 * are already in process.
	 * @param file The storage information for the download.
	 * @param context A Context object.
	 * @param externalOnly true if we're only allowing this file to be download on external storage.
	 * @param showProgress true if we want to display a progress bar during download.
	 * @throws IOException
	 */
	public synchronized void downloadImmediate(BgDownloadFile file, Context context, boolean externalOnly, boolean showProgress) throws IOException
	{
		Log.d(this.getClass().getSimpleName(), "Start downloadImmediate");
		try{
			if(showProgress && context != null && currentDownload != null){
				Toast.makeText(context, DOWNLOAD_WAIT_TEXT, Toast.LENGTH_SHORT).show();
				this.setShowProgress(showProgress);
			}
			if(currentDownload != null){
				Log.d(this.getClass().getSimpleName(), "beginning wait");
				wait();
				Log.d(this.getClass().getSimpleName(), "wait finished");
			}
			
			this.setShowProgress(showProgress);
			currentDownload = file;
			downloadFile(file, context, externalOnly);
			currentDownload = null;
		}catch(InterruptedException ie){
			
		}finally{
			Log.d(this.getClass().getSimpleName(), "sending notify");
			notify();
		}
		Log.d(this.getClass().getSimpleName(), "End downloadImmediate");
	}

	@Override
	protected void downloadFile(BgDownloadFile file, Context context, boolean externalOnly) throws IOException
	{
		Log.d(this.getClass().getSimpleName(), "Starting downloadFile");
		File outputFile = new File(file.outputDirectory, file.outputFilename);
		// Impatience check, make sure this file has not already been downloaded. LP
		if(!file.forceDownload && outputFile.exists())
			return;

		Log.d(this.getClass().getSimpleName(), "downloading "+file.inputUrl);
//		URL url = new URL(file.inputUrl);
		// For Testing only. LP
		URL url = new URL("http://www.explodingzombie.com/files/SANY0015.zip");
		URLConnection conn = url.openConnection();
		if(!(conn instanceof HttpURLConnection)) return;
		
		HttpURLConnection httpConn = (HttpURLConnection)conn;
		ZipInputStream zipStream = null;
		FileOutputStream fileOut = null;
		try{			
			// Download the file zip. LP
			File tempFile = File.createTempFile("ittr", ".zip", file.outputDirectory);
			FileOutputStream tempFileStream = null;
			InputStream inStream = null;
			try{
				inStream = new BufferedInputStream(httpConn.getInputStream());
				tempFileStream = new FileOutputStream(tempFile);
				
				// Progress bar.
				ProgressDialog progress = null;

				Log.d(this.getClass().getSimpleName(), "Beginning file download.");
				byte[] buffer = new byte[4096];
				long count = 0L;
				int n = 0;
				while (-1 != (n = inStream.read(buffer))) {

					if(showProgress && progress == null && context != null){
						progress = new ProgressDialog(context);
						progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
						progress.setMax(100);
						progress.show();
					}else if(!showProgress && progress != null){
						progress.dismiss();
					}
					
					tempFileStream.write(buffer, 0, n);
					count += n;
					if(showProgress && context != null)
						progress.setProgress((int)((count/file.inputSize)*100));
				}
				if(showProgress)
					progress.dismiss();
				Log.d(this.getClass().getSimpleName(), "File download finished");
				
				tempFileStream.flush(); 
			}finally{
				if(inStream != null)
					try{ inStream.close(); }catch(Exception e){}
				if(tempFileStream != null)
					try{ tempFileStream.close(); }catch(Exception e){}
			}
			
			// Extract the video from the zip. LP
			Log.d(this.getClass().getSimpleName(), "Begin extracting video");
			zipStream = new ZipInputStream(new FileInputStream(tempFile));
			ZipEntry entry;
			zipParse : 
			while((entry = zipStream.getNextEntry()) != null){
				String name = entry.getName().toLowerCase();
				if(name.contains("mov") || name.contains("mp4")){
					if(showProgress && context != null)
						Toast.makeText(context, UNZIP_VIDEO_TEXT, Toast.LENGTH_LONG).show();
					
					if(!outputFile.exists() || outputFile.length() != entry.getSize()){
						fileOut = new FileOutputStream(outputFile);
						IOUtils.copy(zipStream, fileOut);
					}
					break zipParse;
				}
			}
			// Make sure to clean up the zip. LP
			tempFile.delete();
			Log.d(this.getClass().getSimpleName(), "End extracting video");
		}finally{
			if(zipStream != null){
				try{ zipStream.close(); }catch(Exception e){}
			}
			if(fileOut != null){
				try{ fileOut.flush(); fileOut.close(); }catch(Exception e){}
			}
		}
		this.setShowProgress(false);
		Log.d(this.getClass().getSimpleName(), "Leaving downloadFile");
	}
}
